#ifndef DSADDIN_H_FDD27C09_AE06_45D2_B3FB_305A6321F275
#define DSADDIN_H_FDD27C09_AE06_45D2_B3FB_305A6321F275
/**
 * \file DSAddIn.h
 *
 * \brief Header file for class CDSAddIn
 *
 * $Id: DSAddIn.h,v 1.1.1.1 2008/04/23 13:29:14 mgh Exp $
 *
 *
 * Copyright (C) 2006 Michael G. Herstine <sp1ff@pobox.com>
 *
 * Permission to use, copy, or modify this source code is hereby granted
 * free of  charge, provided  that this copyright  notice appear  on all
 * copies  and  on   all  source  code  derived  from   this  code.   No
 * representation is made regarding the suitability of this software for
 * any  purpose.  It  is provided  "as  is" without  express or  implied
 * warranty.
 *
 *
 */

#ifndef STDAFX_H_10C3F2AB_C971_462D_AE43_8D659E613A34
# error "#include 'stdafx.h' before this file for PCH!"
#endif // not "stdafx.h"

#ifndef RESOURCE_H_INCLUDED
# include "resource.h"          // Resource definitions
#endif // not "resource.h"

#ifndef SAMPLECAI_H_INCLUDED
# include "SampleCAI.h"         // MIDL-generated COM bindings
#endif // not "SampleCAI.h"

#include "viagui.h"
#include "commands.h"

class CAddIn;                   // Used in the interface, below
class CDSAddIn;                 // Used in the interface, below

/**
 * \class CDSCommands
 *
 * \brief C++ class incarnating the (non-creatable) COM coclass
 * CoDSCommands
 *
 *
 * CDSCommands implements IDSCommands,  the dispatch interface we expose
 * to  DevStudio.  I  suppose I  could have  implemented  IDSCommands on
 * CoDSAddIn  directly,  but  factored  out  the code  for  purposes  of
 * readability.
 *
 *
 */

class CDSCommands :
  public CComObjectRoot,
  public IDispatchImpl<IDSCommands,
                       &IID_IDSCommands,
                       &LIBID_SampleCAILib>,
  public CComCoClass<CDSCommands, &CLSID_CoDSCommands>
{
public:
  /// Initialization routine
  void SetParam(CAddIn *pParent);
  void SetApplicationObject(IApplication* pApplication);
  void SetViaGui(HANDLE hViaGui);

# ifndef DOXYGEN_INVOKED        // Shield the macros from doxygen...
  /// Tell the ATL Registrar *not* to register us
  DECLARE_NO_REGISTRY();
  /// This component is *not* aggregatable
  DECLARE_NOT_AGGREGATABLE(CDSCommands)
  /// Tell ATL which interfaces we support
  BEGIN_COM_MAP(CDSCommands)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY_IID(IID_IDSCommands, IDSCommands)
  END_COM_MAP()
# endif // not DOXYGEN_INVOKED

  //////////////////////////////////////////////////////////////////////
  // Interface IDSCommands
public:
  STDMETHOD_(void, Configure)();
  STDMETHOD_(void, SayHello)();

private:
  /// Non-owning reference to our parent AddIn
  CAddIn *m_pParent;

protected:
	IApplication* m_pApplication;
	HANDLE	m_hViaGui;
};

typedef CComObject<CDSCommands> CCommandsObj;

/**
 * \class CDSAppEvents
 *
 * \brief C++ class sinking DevStudio's events
 *
 *
 * CDSAppEvents exists to "sink", or listen to, DevStudio events.
 *
 *
 */

class CDSAppEvents :
  public CComObjectRoot,
  public IDispatchImpl<IApplicationEvents,
                      &IID_IApplicationEvents,
                      &LIBID_SampleCAILib>,
  public CComCoClass<CDSAppEvents, &CLSID_CoDSAppEvents>
{
public:
  /// SampleCAI initialization routine
  void SetParam(CAddIn *pParent);

# ifndef DOXYGEN_INVOKED        // Shield the macros from doxygen...
  /// Tell the ATL Registrar *not* to register us
  DECLARE_NO_REGISTRY();
  /// This component is *not* aggregatable
  DECLARE_NOT_AGGREGATABLE(CDSAppEvents)
  /// Tell ATL which interfaces we support
  BEGIN_COM_MAP(CDSAppEvents)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY_IID(IID_IApplicationEvents, IApplicationEvents)
  END_COM_MAP()
# endif // not DOXYGEN_INVOKED

  /// Connect to a connection point
  void Connect(IUnknown* pUnk);
  /// Dis-connect from a connection point
  void Disconnect(IUnknown* pUnk);

  //////////////////////////////////////////////////////////////////////
  // Interface IApplicationEvents
public:
  STDMETHOD(BeforeBuildStart)();
  STDMETHOD(BuildFinish)(long nErrors, long nWarnings);
  STDMETHOD(BeforeApplicationShutDown)();
  STDMETHOD(DocumentOpen)(IDispatch *pDocument);
  STDMETHOD(BeforeDocumentClose)(IDispatch *pDocument);
  STDMETHOD(DocumentSave)(IDispatch *pDocument);
  STDMETHOD(NewDocument)(IDispatch *pDocument);
  STDMETHOD(WindowActivate)(IDispatch *pWindow);
  STDMETHOD(WindowDeactivate)(IDispatch *pWindow);
  STDMETHOD(WorkspaceOpen)();
  STDMETHOD(WorkspaceClose)();
  STDMETHOD(NewWorkspace)();

private:
  /// Cookie identifying ourselves to our Connection Point
  DWORD m_dwAdvise;
  /// Non-owning reference to our parent AddIn
  CAddIn *m_pParent;

};

/**
 * \class CDSAddIn
 *
 * \brief Incarnates the SAMPLECAI.CoDSAddIn COM component
 *
 *
 * \note This component is not externally creatable; it is only meant to
 * be aggregated into CoAddIn.
 *
 *
 */

class ATL_NO_VTABLE CDSAddIn :
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CDSAddIn, &CLSID_CoDSAddIn>,
	public ISupportErrorInfo,
	public IDSAddIn
{
public:
  /// ATL requires a default ctor
  CDSAddIn();
  /// ATL-defined initialization routine
  HRESULT FinalConstruct();
  /// ATL-defined cleanup routine
  void FinalRelease();
  /// VisEmacs initialization routine
  void SetParam(CAddIn *pParent);
  void dodebugtest();

# ifndef DOXYGEN_INVOKED        // Shield the macros from doxygen...
  /// Tell the ATL Registrar *not* to register us
  DECLARE_NO_REGISTRY();
  /// This component may only be created as an aggregate
  DECLARE_ONLY_AGGREGATABLE(CDSAddIn)
  /// For GetControllingUnknown
  DECLARE_GET_CONTROLLING_UNKNOWN()
  /// Tell ATL which interfaces we support
  BEGIN_COM_MAP(CDSAddIn)
    COM_INTERFACE_ENTRY(IDSAddIn)
    COM_INTERFACE_ENTRY(ISupportErrorInfo)
  END_COM_MAP()
# endif // not DOXYGEN_INVOKED

  //////////////////////////////////////////////////////////////////////
  // Interface ISupportsErrorInfo
public:
  STDMETHOD(InterfaceSupportsErrorInfo)(/*[in]*/ REFIID riid);

  //////////////////////////////////////////////////////////////////////
  // IDSAddIn
public:
  /// Connect to this AddIn
  STDMETHOD(OnConnection)(IApplication* pApp, VARIANT_BOOL vfFirstTime,
                          long lCookie, VARIANT_BOOL* pvfOnConnection);
  /// Disconnect from this AddIn
  STDMETHOD(OnDisconnection)(VARIANT_BOOL vfLastTime);

private:
  /// Add our commands to DevStudio
  void AddCommands(bool fCreateTb);
  /// Create the VisEmacs toolbar in DevStudio
  void CreateToolbar();

private:
  /// Reg value where we note toolbar creation
  static const TCHAR * const VAL_CREATED_DSTB;
  /// Setting indicated that we've not created our toolbar
  static const DWORD VAL_CREATED_DSTB_NO = 0x00;
  /// Setting indicated that we've created our toolbar
  static const DWORD VAL_CREATED_DSTB_YES = 0x01;
  /// Base for our message window name
  static const TCHAR * const WND_BASE_NAME;
  /// Window Class Name for our message window
  static const TCHAR * const WND_CLASS_NAME;
  /// Maximum window name length
  static const size_t WND_NAME_STR_LEN = 61 + 8 + 3 + 1;
  /// Private Window message
  static const UINT WM_CREATETOOLBAR = WM_USER + 0x100;
  /// CBT hook for re-naming our toolbar
  static LRESULT CALLBACK DsToolbarHook(int nCode,
                                        WPARAM wParam,
                                        LPARAM lParam);
  /// Window procedure for our hidden message window
  static LRESULT CALLBACK MsgWindowProc(HWND hWnd, UINT nMsg,
                                        WPARAM wParam, LPARAM lParam);
private:
  /// IApplication reference to the DevStudio Application object
  CComPtr<IApplication> m_pApp;
  /// Event Sink for DevStudio App events
  CComObject<CDSAppEvents> *m_pAppEvents;
  /// App-provided cookie naming this AddIn to DevStudio
  long m_lCookie;
  /// Non-owning reference to our parent CAddIn instance
  CAddIn *m_pParent;
  /// Handle to our message window
  HWND m_hWnd;

  CCommandsObj *m_pCmds;

  HANDLE	m_hViaGui;
  HANDLE	m_hViaCommands;
};

// Enter ourself in this server's object map
OBJECT_ENTRY_AUTO(__uuidof(CoDSAddIn), CDSAddIn)

// Local Variables:
// fill-column: 72
// indent-tabs-mode: nil
// show-trailing-whitespace: t
// End:

#endif // DSADDIN_H_FDD27C09_AE06_45D2_B3FB_305A6321F275
